<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>实时波形显示器</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Arial', sans-serif;
            background-color: #1e1e2e;
            color: #cdd6f4;
            height: 100vh;
            overflow: hidden;
            display: flex;
            flex-direction: column;
        }
        
        header {
            background-color: #313244;
            padding: 15px 20px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
        }
        
        h1 {
            font-size: 1.5rem;
            color: #89b4fa;
        }
        
        .controls {
            display: flex;
            gap: 15px;
        }
        
        button {
            background-color: #585b70;
            color: #cdd6f4;
            border: none;
            padding: 8px 15px;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s;
        }
        
        button:hover {
            background-color: #6c7086;
        }
        
        .container {
            flex: 1;
            display: flex;
            flex-direction: column;
            padding: 20px;
            gap: 20px;
            overflow: hidden;
        }
        
        .canvas-container {
            flex: 1;
            position: relative;
            background-color: #181825;
            border-radius: 8px;
            overflow: hidden;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
        }
        
        canvas {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        }
        
        .channel-info {
            display: flex;
            justify-content: space-around;
            background-color: #313244;
            padding: 10px;
            border-radius: 6px;
        }
        
        .channel {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .color-indicator {
            width: 20px;
            height: 20px;
            border-radius: 4px;
        }
        
        .ch0 { background-color: #f38ba8; }
        .ch1 { background-color: #89b4fa; }
        
        footer {
            text-align: center;
            padding: 10px;
            background-color: #313244;
            font-size: 0.9rem;
            color: #a6adc8;
        }
        
        @media (max-width: 768px) {
            header {
                flex-direction: column;
                gap: 10px;
            }
            
            .controls {
                width: 100%;
                justify-content: center;
            }
            
            .channel-info {
                flex-direction: column;
                gap: 10px;
            }
        }
    </style>
</head>
<body>
    <header>
        <h1>实时波形显示器</h1>
        <div class="controls">
            <button id="pauseBtn">暂停</button>
            <button id="resetBtn">重置视图</button>
        </div>
    </header>
    
    <div class="container">
        <div class="canvas-container">
            <canvas id="waveformCanvas"></canvas>
        </div>
        
        <div class="channel-info">
            <div class="channel">
                <div class="color-indicator ch0"></div>
                <span>通道 0</span>
            </div>
            <div class="channel">
                <div class="color-indicator ch1"></div>
                <span>通道 1</span>
            </div>
        </div>
    </div>
    
    <footer>
        采样率: 1000 Hz | 时间范围: 10分钟 | 数据格式: uint16 (0-65535)
    </footer>

    <script>
        // 配置参数
        const config = {
            sampleRate: 1000,       // 采样率 (Hz)
            timeRange: 600,         // 时间范围 (秒) - 10分钟
            channels: 2,            // 通道数量
            updateInterval: 1000,    // 更新间隔 (ms)
            maxPoints: 1920 * 2      // 最大绘制点数 (基于屏幕宽度)
        };
        
        // 全局变量
        let canvas, ctx;
        let dataBuffer = { ch0: [], ch1: [] };
        let isPaused = false;
        let animationId;
        let lastUpdateTime = 0;
        
        // 初始化函数
        function init() {
            // 获取Canvas元素和上下文
            canvas = document.getElementById('waveformCanvas');
            ctx = canvas.getContext('2d');
            
            // 设置Canvas尺寸
            resizeCanvas();
            
            // 初始化数据缓冲区
            for (let i = 0; i < config.timeRange * config.sampleRate; i++) {
                dataBuffer.ch0.push(0);
                dataBuffer.ch1.push(0);
            }
            
            // 加载初始数据
            loadInitialData();
            
            // 设置事件监听器
            window.addEventListener('resize', resizeCanvas);
            document.getElementById('pauseBtn').addEventListener('click', togglePause);
            document.getElementById('resetBtn').addEventListener('click', resetView);
            
            // 开始动画循环
            requestAnimationFrame(drawWaveforms);
        }
        
        // 调整Canvas大小以适应窗口
        function resizeCanvas() {
            const container = canvas.parentElement;
            canvas.width = container.clientWidth;
            canvas.height = container.clientHeight;
        }
        
        // 加载初始数据
        async function loadInitialData() {
            try {
                const response = await fetch('/init_data');
                const data = await response.json();
                
                // 填充数据缓冲区
                dataBuffer.ch0 = data.ch0;
                dataBuffer.ch1 = data.ch1;
                
                // 开始定时更新
                setInterval(fetchUpdateData, config.updateInterval);
            } catch (error) {
                console.error('加载初始数据失败:', error);
                // 重试
                setTimeout(loadInitialData, 2000);
            }
        }
        
        // 获取增量更新数据
        async function fetchUpdateData() {
            if (isPaused) return;
            
            try {
                const response = await fetch('/update_data');
                const newData = await response.json();
                
                // 更新数据缓冲区 - 移除旧数据，添加新数据
                const pointsToRemove = newData.ch0.length;
                dataBuffer.ch0.splice(0, pointsToRemove);
                dataBuffer.ch0.push(...newData.ch0);
                
                dataBuffer.ch1.splice(0, pointsToRemove);
                dataBuffer.ch1.push(...newData.ch1);
            } catch (error) {
                console.error('获取更新数据失败:', error);
            }
        }
        
        // 绘制波形
        function drawWaveforms(timestamp) {
            // 计算时间差，限制绘制频率
            const deltaTime = timestamp - lastUpdateTime;
            if (deltaTime < 16) { // ~60fps
                animationId = requestAnimationFrame(drawWaveforms);
                return;
            }
            lastUpdateTime = timestamp;
            
            // 清除画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            // 绘制网格和坐标轴
            drawGrid();
            
            // 绘制通道0波形
            drawChannel(dataBuffer.ch0, '#f38ba8');
            
            // 绘制通道1波形
            drawChannel(dataBuffer.ch1, '#89b4fa');
            
            // 绘制图例
            drawLegend();
            
            // 继续动画循环
            animationId = requestAnimationFrame(drawWaveforms);
        }
        
        // 绘制网格和坐标轴
        function drawGrid() {
            const width = canvas.width;
            const height = canvas.height;
            const padding = 40;
            
            // 设置样式
            ctx.strokeStyle = '#45475a';
            ctx.lineWidth = 1;
            ctx.setLineDash([5, 3]);
            
            // 绘制水平网格线
            const yStep = height / 4;
            for (let i = 1; i < 4; i++) {
                const y = i * yStep;
                ctx.beginPath();
                ctx.moveTo(padding, y);
                ctx.lineTo(width - padding, y);
                ctx.stroke();
            }
            
            // 绘制垂直网格线 (时间标记)
            const timeStep = 60; // 每60秒一条线
            const xStep = (width - 2 * padding) / (config.timeRange / timeStep);
            for (let i = 1; i < config.timeRange / timeStep; i++) {
                const x = padding + i * xStep;
                ctx.beginPath();
                ctx.moveTo(x, padding);
                ctx.lineTo(x, height - padding);
                ctx.stroke();
                
                // 添加时间标签
                const minutes = Math.floor((i * timeStep) / 60);
                const seconds = (i * timeStep) % 60;
                ctx.fillStyle = '#6c7086';
                ctx.font = '12px Arial';
                ctx.fillText(`${minutes}:${seconds.toString().padStart(2, '0')}`, x - 15, height - 15);
            }
            
            // 重置虚线
            ctx.setLineDash([]);
            
            // 绘制坐标轴
            ctx.strokeStyle = '#6c7086';
            ctx.lineWidth = 2;
            
            // X轴
            ctx.beginPath();
            ctx.moveTo(padding, height - padding);
            ctx.lineTo(width - padding, height - padding);
            ctx.stroke();
            
            // Y轴
            ctx.beginPath();
            ctx.moveTo(padding, padding);
            ctx.lineTo(padding, height - padding);
            ctx.stroke();
            
            // 添加Y轴标签
            ctx.fillStyle = '#6c7086';
            ctx.font = '12px Arial';
            ctx.textAlign = 'right';
            ctx.textBaseline = 'middle';
            
            const maxValue = 65535;
            for (let i = 0; i <= 4; i++) {
                const value = Math.round(maxValue * (1 - i/4));
                const y = padding + i * yStep;
                ctx.fillText(value.toString(), padding - 10, y);
            }
        }
        
        // 绘制单个通道波形
        function drawChannel(data, color) {
            const width = canvas.width;
            const height = canvas.height;
            const padding = 40;
            const maxValue = 65535;
            
            // 计算降采样因子
            const totalPoints = data.length;
            const drawWidth = width - 2 * padding;
            const pointsToDraw = Math.min(totalPoints, config.maxPoints);
            const step = Math.max(1, Math.floor(totalPoints / pointsToDraw));
            
            // 设置样式
            ctx.strokeStyle = color;
            ctx.lineWidth = 2;
            ctx.beginPath();
            
            // 绘制波形
            for (let i = 0; i < pointsToDraw; i++) {
                const index = Math.floor(i * step);
                if (index >= totalPoints) break;
                
                const value = data[index];
                const x = padding + (i / pointsToDraw) * drawWidth;
                const y = padding + (height - 2 * padding) * (1 - value / maxValue);
                
                if (i === 0) {
                    ctx.moveTo(x, y);
                } else {
                    ctx.lineTo(x, y);
                }
            }
            
            ctx.stroke();
        }
        
        // 绘制图例
        function drawLegend() {
            ctx.font = '14px Arial';
            ctx.textAlign = 'left';
            ctx.textBaseline = 'top';
            
            // 通道0
            ctx.fillStyle = '#f38ba8';
            ctx.fillText('通道 0', canvas.width - 120, 20);
            
            // 通道1
            ctx.fillStyle = '#89b4fa';
            ctx.fillText('通道 1', canvas.width - 120, 45);
            
            // 状态
            ctx.fillStyle = isPaused ? '#f38ba8' : '#a6e3a1';
            ctx.fillText(isPaused ? '已暂停' : '运行中', canvas.width - 120, 70);
        }
        
        // 切换暂停状态
        function togglePause() {
            isPaused = !isPaused;
            const btn = document.getElementById('pauseBtn');
            btn.textContent = isPaused ? '继续' : '暂停';
        }
        
        // 重置视图
        function resetView() {
            resizeCanvas();
        }
        
        // 页面加载完成后初始化
        window.addEventListener('load', init);
    </script>
</body>
</html>